import 'package:flutter/material.dart';

///x轴数据
class BarChartX {
  ///x轴具体的坐标刻度
  final List<String> xList;

  ///x轴需要显示的坐标刻度
  final List<String> xShowList;

  BarChartX(this.xList, this.xShowList);
}

///y轴数据
class BarChartY {
  ///y轴具体的坐标刻度
  final List<String> yList;

  ///y轴的总值
  final double? yTotal;

  BarChartY(this.yList, {this.yTotal});
}

/// Y轴区间底色配置
class YBackgroundBand {
  final double start; // 起始值（包含）
  final double end;   // 结束值（包含）
  final Color color;  // 底色
  const YBackgroundBand({required this.start, required this.end, required this.color});
}

///柱状图分段数据
class BarChartSegment {
  ///柱状图分段起始值
  final double start;

  ///柱状图分段结束值
  final double end;

  ///柱状图的颜色
  final Color? barColor;

  ///选中柱状图的颜色
  final Color? selectedBarColor;

  // 点状图配置：形状、尺寸、圆角、颜色
  final double? pointSize; // 默认小方块/圆点尺寸
  final BorderRadius? pointRadius; // 小方块的圆角（圆点时忽略）
  final bool? pointIsCircle; // 是否使用圆点（默认方块）
  final Color? pointColor; // 点颜色（未指定则使用barColor）
  final Color? selectedPointColor; // 选中点颜色（未指定则使用selectedBarColor）
  
  /// 是否点状显示（可覆盖 BarChartWidget.useDotChart）
  final bool? useDotChart;

  BarChartSegment(
    this.start,
    this.end, {
    this.barColor,
    this.selectedBarColor,
    this.pointSize,
    this.pointRadius,
    this.pointIsCircle,
    this.pointColor,
    this.selectedPointColor,
    this.useDotChart,
  });
}

///柱状图数据
class BarChartData {
  ///柱状图具体的坐标刻度
  final String x;
  final List<BarChartSegment> segments;

  BarChartData(this.x, this.segments);
}

class BarChartWidget extends StatefulWidget {
  ///x轴
  final BarChartX x;

  ///y轴
  final BarChartY y;

  ///柱状图数据
  final List<BarChartData> data;

  ///x轴的粗细
  final double xAxisStrokeWidth;

  ///x轴的颜色
  final Color xAxisColor;

  ///x轴的文字大小
  final double xAxisTextSize;

  ///x轴的文字颜色
  final Color xAxisTextColor;

  ///y轴的粗细
  final double yAxisStrokeWidth;

  ///y轴的颜色
  final Color yAxisColor;

  ///y轴的文字大小
  final double yAxisTextSize;

  ///y轴的文字颜色
  final Color yAxisTextColor;

  ///分段虚线的粗细
  final double segmentLineStrokeWidth;

  ///分段虚线的颜色
  final Color segmentLineColor;

  ///柱状图的颜色
  final Color barColor;

  ///柱状图的圆角
  final BorderRadius? barRadius;

  ///柱状图的底色（可选，每柱基础背景色）
  final List<Color>? barBaseColors;

  /// Y轴区间底色（可选，支持多个区间）
  final List<YBackgroundBand>? yBackgroundBands;

  ///柱状图的间距与柱状图宽度的比值
  final double? barSpacingRatio;

  ///选中柱状图的颜色
  final Color selectedBarColor;

  ///选中柱状图标记线的粗细
  final double selectedBarMarkLineStrokeWidth;

  ///选中柱状图标记线的颜色
  final Color selectedBarMarkLineColor;

  ///选中柱状图标记线顶部显示的文字大小
  final double selectedBarMarkLineTextSize;

  ///选中柱状图标记线顶部显示的文字颜色
  final Color selectedBarMarkLineTextColor;

  /// 选中柱状图标记线顶部自定义Widget构建器（提供则替换默认文字）
  final Widget Function(BuildContext context, BarChartData selected)? selectedMarkTopBuilder;

  /// 顶部自定义区域的预留高度（提供selectedMarkTopBuilder时生效）
  final double? topOverlayHeight;

  /// y轴是否在右侧（默认左侧）
  final bool yAxisOnRight;

  /// 是否启用点状图模式（默认禁用，表现为柱状图）
  final bool useDotChart;

  /// 是否显示X轴（默认显示）
  final bool showXAxis;

  /// 是否显示Y轴（默认显示）
  final bool showYAxis;

  /// 是否显示X轴文字（默认显示）
  final bool showXAxisLabels;

  /// 是否显示Y轴文字（默认显示）
  final bool showYAxisLabels;

  /// 是否显示分段虚线（默认显示）
  final bool showSegmentLines;

  /// 是否显示选中竖线（默认显示）
  final bool showSelectedVerticalLine;

  /// 是否启用柱状图增长动画（默认false，仅柱状图生效）
  final bool enableGrowthAnimation;

  /// 柱状图增长动画时长
  final Duration growthDuration;

  ///柱子点击事件
  final Function(String?)? onBarSelected;

  const BarChartWidget(
      {super.key,
      required this.x,
      required this.y,
      required this.data,
      this.xAxisStrokeWidth = 1,
      this.xAxisColor = Colors.black,
      this.xAxisTextSize = 12,
      this.xAxisTextColor = Colors.black,
      this.yAxisStrokeWidth = 1,
      this.yAxisColor = Colors.black,
      this.yAxisTextSize = 12,
      this.yAxisTextColor = Colors.black,
      this.segmentLineStrokeWidth = 1,
      this.segmentLineColor = Colors.grey,
      this.barColor = Colors.blue,
      this.barRadius,
      this.barBaseColors,
      this.yBackgroundBands,
      this.barSpacingRatio,
      this.selectedBarColor = Colors.red,
      this.selectedBarMarkLineStrokeWidth = 1,
      this.selectedBarMarkLineColor = Colors.black,
      this.selectedBarMarkLineTextSize = 12,
      this.selectedBarMarkLineTextColor = Colors.black,
      this.yAxisOnRight = false,
      this.useDotChart = false,
      this.showXAxis = true,
      this.showYAxis = true,
      this.showXAxisLabels = true,
      this.showYAxisLabels = true,
      this.showSegmentLines = true,
      this.showSelectedVerticalLine = true,
      this.enableGrowthAnimation = false,
      this.growthDuration = const Duration(milliseconds: 800),
      this.topOverlayHeight,
      this.selectedMarkTopBuilder,
      this.onBarSelected});

  @override
  State<BarChartWidget> createState() => _BarChartWidgetState();
}

class _BarChartWidgetState extends State<BarChartWidget> with TickerProviderStateMixin {
  BarChartData? _selectedBar;
  AnimationController? _growthController;

  // 顶部悬浮自定义Widget的尺寸测量
  final GlobalKey _selectedTopKey = GlobalKey();
  double _selectedTopHeight = 0.0;
  double _selectedTopWidth = 0.0;

  @override
  void initState() {
    super.initState();
    _initGrowthAnimation();
  }

  void _initGrowthAnimation() {
    _growthController?.dispose();
    if (widget.enableGrowthAnimation && !widget.useDotChart) {
      _growthController = AnimationController(vsync: this, duration: widget.growthDuration)
        ..addListener(() {
          setState(() {});
        })
        ..forward(from: 0);
    } else {
      _growthController = null;
    }
  }

  @override
  void didUpdateWidget(covariant BarChartWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    final dataChanged = !identical(oldWidget.data, widget.data) || oldWidget.data.length != widget.data.length;
    final modeChanged = oldWidget.useDotChart != widget.useDotChart;
    final animFlagChanged = oldWidget.enableGrowthAnimation != widget.enableGrowthAnimation || oldWidget.growthDuration != widget.growthDuration;
    if (dataChanged || modeChanged || animFlagChanged) {
      _initGrowthAnimation();
    }
  }

  @override
  void dispose() {
    _growthController?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (details) {
        print("onTapDown called");
        final RenderBox renderBox = context.findRenderObject() as RenderBox;
        final localPosition = renderBox.globalToLocal(details.globalPosition);
        print("localPosition: $localPosition");

        double yAxisWidth = 0;
        if (widget.showYAxisLabels) {
          for (var value in widget.y.yList) {
            final textPainter = TextPainter(
              text: TextSpan(
                text: value,
                style: TextStyle(
                  color: widget.yAxisTextColor,
                  fontSize: widget.yAxisTextSize,
                ),
              ),
              textDirection: TextDirection.ltr,
            );
            textPainter.layout();
            if (yAxisWidth < textPainter.width) {
              yAxisWidth = textPainter.width;
            }
          }
          yAxisWidth += 10;
        } else {
          yAxisWidth = 0; // 不显示Y轴文字时不占用横向空间
        }
        print("yAxisWidth: $yAxisWidth");

        final barSpacingRatio = widget.barSpacingRatio ?? (widget.x.xList.length > 20 ? 1.0 : 1.5);
        final axisX = widget.yAxisOnRight ? renderBox.size.width - yAxisWidth : yAxisWidth;
        final chartStartX = widget.yAxisOnRight ? 0.0 : axisX;
        final chartEndX = widget.yAxisOnRight ? axisX : renderBox.size.width - 10.0;
        final availableWidth = (chartEndX - chartStartX);
        final barWidth = availableWidth / (widget.x.xList.length * (1 + barSpacingRatio) + barSpacingRatio);
        final barSpacing = barWidth * barSpacingRatio;
        print("barWidth: $barWidth");

        if (barWidth <= 0) return;

        BarChartData? newSelectedBar;
        for (int i = 0; i < widget.x.xList.length; i++) {
          final x = chartStartX + barSpacing / 2 + i * (barWidth + barSpacing);
          final rect = Rect.fromLTWH(x, 0, barWidth + barSpacing, renderBox.size.height);
          if (rect.contains(localPosition)) {
            final xValue = widget.x.xList[i];
            try {
              newSelectedBar = widget.data.firstWhere((element) => element.x == xValue);
            } catch (e) {
              newSelectedBar = null;
            }
            break;
          }
        }

        setState(() {
          if (newSelectedBar != null) {
            if (_selectedBar == newSelectedBar) {
              _selectedBar = null;
              widget.onBarSelected?.call(null);
            } else {
              _selectedBar = newSelectedBar;
              widget.onBarSelected?.call(_selectedBar!.x);
            }
          } else {
            _selectedBar = null;
            widget.onBarSelected?.call(null);
          }
        });
      },
      child: Stack(
         clipBehavior: Clip.none,
         children: [
           CustomPaint(
             painter: _BarChartPainter(widget, selectedBar: _selectedBar, growthProgress: (_growthController?.value ?? 1.0)),
             size: Size.infinite,
           ),
           if (_selectedBar != null && widget.selectedMarkTopBuilder != null)
             Positioned.fill(
               child: LayoutBuilder(builder: (context, constraints) {
                 final Size size = constraints.biggest;
 
                 double yAxisWidth = 0;
                 if (widget.showYAxisLabels) {
                   for (var value in widget.y.yList) {
                     final tp = TextPainter(
                       text: TextSpan(
                         text: value,
                         style: TextStyle(
                           color: widget.yAxisTextColor,
                           fontSize: widget.yAxisTextSize,
                         ),
                       ),
                       textDirection: TextDirection.ltr,
                     );
                     tp.layout();
                     if (yAxisWidth < tp.width) {
                       yAxisWidth = tp.width;
                     }
                   }
                   yAxisWidth += 10;
                 }
 
                 final sampleTextPainter = TextPainter(
                   text: TextSpan(
                     text: "00:00",
                     style: TextStyle(
                       color: widget.xAxisTextColor,
                       fontSize: widget.xAxisTextSize,
                     ),
                   ),
                   textDirection: TextDirection.ltr,
                 );
                 sampleTextPainter.layout();
                 final double xAxisHeight = widget.showXAxisLabels ? (sampleTextPainter.height + 10) : 0;
 
                 final axisX = widget.yAxisOnRight ? size.width - yAxisWidth : yAxisWidth;
                 final chartStartX = widget.yAxisOnRight ? 0.0 : axisX;
                 final chartEndX = widget.yAxisOnRight ? axisX : size.width - 10.0;
 
                 final barSpacingRatio = widget.barSpacingRatio ?? (widget.x.xList.length > 20 ? 1.0 : 1.5);
                 final availableWidth = (chartEndX - chartStartX);
                 final barWidth = availableWidth / (widget.x.xList.length * (1 + barSpacingRatio) + barSpacingRatio);
                 final barSpacing = barWidth * barSpacingRatio;
 
                 final xIndex = widget.x.xList.indexOf(_selectedBar!.x);
                 if (xIndex < 0) return const SizedBox.shrink();
 
                 final barLeft = chartStartX + barSpacing + xIndex * (barWidth + barSpacing);
                 final barCenterX = barLeft + barWidth / 2;
                 final fullWidth = size.width;
                 final xFractionFull = fullWidth > 0 ? (barCenterX / fullWidth).clamp(0.0, 1.0) : 0.0;
 
                 // 测量并更新顶部自定义Widget尺寸，以便悬浮到图表外部并严格居中
                 WidgetsBinding.instance.addPostFrameCallback((_) {
                   final ctx = _selectedTopKey.currentContext;
                   if (ctx != null) {
                     final rb = ctx.findRenderObject() as RenderBox?;
                     final h = rb?.size.height ?? 0.0;
                     final w = rb?.size.width ?? 0.0;
                     if (h != _selectedTopHeight || w != _selectedTopWidth) {
                       setState(() {
                         _selectedTopHeight = h;
                         _selectedTopWidth = w;
                       });
                     }
                   }
                 });
 
                 final double floatOffset = -(_selectedTopHeight > 0 ? _selectedTopHeight : (widget.topOverlayHeight ?? 0.0));
                 final double left = barCenterX - (_selectedTopWidth > 0 ? _selectedTopWidth / 2 : 0.0);
 
                 return IgnorePointer(
                   child: Stack(
                     clipBehavior: Clip.none,
                     children: [
                       Positioned(
                         left: left,
                         top: floatOffset,
                         child: KeyedSubtree(
                           key: _selectedTopKey,
                           child: widget.selectedMarkTopBuilder!(context, _selectedBar!),
                         ),
                       ),
                     ],
                   ),
                 );
               }),
             ),
         ],
       ),
    );
  }
}

class _BarChartPainter extends CustomPainter {
  final BarChartWidget widget;
  final BarChartData? selectedBar;
  final double growthProgress;

  _BarChartPainter(this.widget, {this.selectedBar, this.growthProgress = 1.0});

  @override
  void paint(Canvas canvas, Size size) {
    print("paint called");
    // Define properties from widget
    final x = widget.x;
    final y = widget.y;
    final data = widget.data;
    final xAxisStrokeWidth = widget.xAxisStrokeWidth;
    final xAxisColor = widget.xAxisColor;
    final xAxisTextSize = widget.xAxisTextSize;
    final xAxisTextColor = widget.xAxisTextColor;
    final yAxisStrokeWidth = widget.yAxisStrokeWidth;
    final yAxisColor = widget.yAxisColor;
    final yAxisTextSize = widget.yAxisTextSize;
    final yAxisTextColor = widget.yAxisTextColor;
    final segmentLineStrokeWidth = widget.segmentLineStrokeWidth;
    final segmentLineColor = widget.segmentLineColor;
      final barColor = widget.barColor;
      final barRadius = widget.barRadius;
      final selectedBarColor = widget.selectedBarColor;
    final useDotChart = widget.useDotChart;
    final bool enableGrowth = widget.enableGrowthAnimation && !useDotChart;
      final selectedLineWidth = widget.selectedBarMarkLineStrokeWidth;
    final selectedLineColor = widget.selectedBarMarkLineColor;
    final selectedTextSize = widget.selectedBarMarkLineTextSize;
    final selectedTextColor = widget.selectedBarMarkLineTextColor;
    final showXAxis = widget.showXAxis;
    final showYAxis = widget.showYAxis;
    final showXAxisLabels = widget.showXAxisLabels;
    final showYAxisLabels = widget.showYAxisLabels;
    final showSegmentLines = widget.showSegmentLines;
    final barBaseColors = widget.barBaseColors;
    final yBackgroundBands = widget.yBackgroundBands;

    // Calculate dimensions
    double yAxisWidth = 0;
    if (showYAxisLabels) {
      for (var value in y.yList) {
        final textPainter = TextPainter(
          text: TextSpan(
            text: value,
            style: TextStyle(
              color: yAxisTextColor,
              fontSize: yAxisTextSize,
            ),
          ),
          textDirection: TextDirection.ltr,
        );
        textPainter.layout();
        if (yAxisWidth < textPainter.width) {
          yAxisWidth = textPainter.width;
        }
      }
      yAxisWidth += 10;
    } else {
      yAxisWidth = 0;
    }
    print("yAxisWidth: $yAxisWidth");

    final sampleTextPainter = TextPainter(
      text: TextSpan(
        text: "00:00",
        style: TextStyle(
          color: xAxisTextColor,
          fontSize: xAxisTextSize,
        ),
      ),
      textDirection: TextDirection.ltr,
    );
    sampleTextPainter.layout();
    double xAxisHeight = showXAxisLabels ? (sampleTextPainter.height + 10) : 0;
    print("xAxisHeight: $xAxisHeight");

    // Draw Y-axis
    final yAxisPaint = Paint()
      ..strokeWidth = yAxisStrokeWidth
      ..color = yAxisColor;

    final axisX = widget.yAxisOnRight ? size.width - yAxisWidth : yAxisWidth;
    final chartStartX = widget.yAxisOnRight ? 0.0 : axisX;
    final chartEndX = widget.yAxisOnRight ? axisX : size.width - 10.0;

    if (showYAxis) {
      canvas.drawLine(
        Offset(axisX, 0),
        Offset(axisX, size.height - xAxisHeight),
        yAxisPaint,
      );
    }

    // 在绘制分段虚线之前绘制 Y 轴区间底色（位于背景，不影响柱子和虚线）
    if (yBackgroundBands != null && yBackgroundBands.isNotEmpty) {
      final double yMinBg = y.yList.isNotEmpty ? double.tryParse(y.yList.first) ?? 0.0 : 0.0;
      final double yMaxBg = y.yTotal ?? (y.yList.isNotEmpty ? double.tryParse(y.yList.last) ?? 0.0 : 0.0);
      final double yRangeBg = yMaxBg - yMinBg;
      if (yRangeBg > 0) {
        for (final band in yBackgroundBands) {
          final double startVal = band.start.clamp(yMinBg, yMaxBg).toDouble();
          final double endVal = band.end.clamp(yMinBg, yMaxBg).toDouble();
          if (endVal <= startVal) continue;
           final double yPosStart = (size.height - xAxisHeight) * (1 - (startVal - yMinBg) / yRangeBg);
           final double yPosEnd = (size.height - xAxisHeight) * (1 - (endVal - yMinBg) / yRangeBg);
           final rect = Rect.fromLTWH(chartStartX, yPosEnd, chartEndX - chartStartX, yPosStart - yPosEnd);
           final paint = Paint()
             ..color = band.color
             ..style = PaintingStyle.fill;
           canvas.drawRect(rect, paint);
         }
       }
     }
    // Draw X-axis
    final xAxisPaint = Paint()
      ..strokeWidth = xAxisStrokeWidth
      ..color = xAxisColor;
    if (showXAxis) {
      canvas.drawLine(
        Offset(chartStartX, size.height - xAxisHeight),
        Offset(chartEndX, size.height - xAxisHeight),
        xAxisPaint,
      );
    }

    // Draw Y-axis labels and dashed lines
    final yAxisSegmentHeight = (size.height - xAxisHeight) / (y.yList.length - 1);
    for (int i = 0; i < y.yList.length; i++) {
      final yPos = (size.height - xAxisHeight) - yAxisSegmentHeight * i;
      if (showYAxisLabels) {
        final textPainter = TextPainter(
          text: TextSpan(
            text: y.yList[i],
            style: TextStyle(
              color: yAxisTextColor,
              fontSize: yAxisTextSize,
            ),
          ),
          textDirection: TextDirection.ltr,
        );
        textPainter.layout();
        textPainter.paint(
          canvas,
          widget.yAxisOnRight
              ? Offset(axisX + 5, yPos - textPainter.height / 2)
              : Offset(axisX - textPainter.width - 5, yPos - textPainter.height / 2),
        );
      }

      if (showSegmentLines && i > 0) {
        final dashPaint = Paint()
          ..color = segmentLineColor
          ..strokeWidth = segmentLineStrokeWidth;
        const double dashWidth = 4;
        const double dashSpace = 4;
        double startX = chartStartX;
        while (startX < chartEndX) {
          final nextX = startX + dashWidth;
          canvas.drawLine(
            Offset(startX, yPos),
            Offset(nextX > chartEndX ? chartEndX : nextX, yPos),
            dashPaint,
          );
          startX += dashWidth + dashSpace;
        }
      }
    }

    // Draw X-axis labels
    if (showXAxisLabels && x.xShowList.isNotEmpty) {
      final xAxisSegmentWidth = (chartEndX - chartStartX) / (x.xShowList.length - 1);
      for (int i = 0; i < x.xShowList.length; i++) {
        final text = x.xShowList[i];
        final textPainter = TextPainter(
          text: TextSpan(
            text: text,
            style: TextStyle(
              color: xAxisTextColor,
              fontSize: xAxisTextSize,
            ),
          ),
          textDirection: TextDirection.ltr,
        );
        textPainter.layout();

        double xPos;
        if (i == 0) {
          xPos = chartStartX;
        } else if (i == x.xShowList.length - 1) {
          xPos = chartEndX - textPainter.width;
        } else {
          xPos = chartStartX + xAxisSegmentWidth * i - textPainter.width / 2;
        }

        textPainter.paint(
          canvas,
          Offset(xPos, size.height - xAxisHeight + 5),
        );
      }
    }

    // Draw bars or dots
    final barSpacingRatio = widget.barSpacingRatio ?? (x.xList.length > 20 ? 1.0 : 1.5);
    final availableWidth = (chartEndX - chartStartX);
    final barWidth = availableWidth / (x.xList.length * (1 + barSpacingRatio) + barSpacingRatio);
    final barSpacing = barWidth * barSpacingRatio;
    print("barWidth: $barWidth");

    if (barWidth <= 0) return;

    // Draw base background for each bar (if provided), even for x with no data
    if (barBaseColors != null) {
      for (int xi = 0; xi < x.xList.length; xi++) {
        final baseColor = xi < barBaseColors.length ? barBaseColors[xi] : null;
        if (baseColor == null) continue;
        final barLeft = chartStartX + barSpacing + xi * (barWidth + barSpacing);
        final rectBg = Rect.fromLTWH(barLeft, 0, barWidth, size.height - xAxisHeight);
        final bgPaint = Paint()
          ..color = baseColor
          ..style = PaintingStyle.fill;
        if (barRadius != null) {
          canvas.drawRRect(
            RRect.fromRectAndCorners(
              rectBg,
              topLeft: barRadius.topLeft,
              topRight: barRadius.topRight,
              bottomLeft: barRadius.bottomLeft,
              bottomRight: barRadius.bottomRight,
            ),
            bgPaint,
          );
        } else {
          canvas.drawRect(rectBg, bgPaint);
        }
      }
    }

    final yMin = y.yList.isNotEmpty ? double.tryParse(y.yList.first) ?? 0.0 : 0.0;
    final yMax = y.yTotal ?? (y.yList.isNotEmpty ? double.tryParse(y.yList.last) ?? 0.0 : 0.0);
    final yRange = yMax - yMin;
    if (yRange <= 0) return;

    for (int i = 0; i < data.length; i++) {
      final item = data[i];
      final xIndex = x.xList.indexOf(item.x);
      if (xIndex == -1) continue;

      final barLeft = chartStartX + barSpacing + xIndex * (barWidth + barSpacing);
      final barCenterX = barLeft + barWidth / 2;

      if (item.segments.isNotEmpty) {
        for (var segment in item.segments) {
          final bool segmentUseDot = segment.useDotChart ?? widget.useDotChart;
          if (!segmentUseDot) {
            // 柱状图绘制（支持增长动画，仅对柱状段生效）
            final bool enableGrowthForSegment = widget.enableGrowthAnimation && !segmentUseDot;
            final animatedStart = enableGrowthForSegment ? (yMin + (segment.start - yMin) * growthProgress) : segment.start;
            final animatedEnd = enableGrowthForSegment ? (yMin + (segment.end - yMin) * growthProgress) : segment.end;
            final yPosStart = (size.height - xAxisHeight) * (1 - (animatedStart - yMin) / yRange);
            final yPosEnd = (size.height - xAxisHeight) * (1 - (animatedEnd - yMin) / yRange);
            final rect = Rect.fromLTWH(barLeft, yPosEnd, barWidth, yPosStart - yPosEnd);
            final paint = Paint()
              ..color = selectedBar == item ? (segment.selectedBarColor ?? selectedBarColor) : (segment.barColor ?? barColor)
              ..style = PaintingStyle.fill;

            if (barRadius != null) {
              canvas.drawRRect(
                RRect.fromRectAndCorners(
                  rect,
                  topLeft: barRadius.topLeft,
                  topRight: barRadius.topRight,
                  bottomLeft: barRadius.bottomLeft,
                  bottomRight: barRadius.bottomRight,
                ),
                paint,
              );
            } else {
              canvas.drawRect(rect, paint);
            }
          } else {
            // 点状图绘制（使用 end 作为点的Y值）
            final valueY = (size.height - xAxisHeight) * (1 - (segment.end - yMin) / yRange);
            final sizePx = segment.pointSize ?? 8.0;
            final isCircle = segment.pointIsCircle ?? false;
            final paint = Paint()
              ..color = selectedBar == item
                  ? (segment.selectedPointColor ?? segment.selectedBarColor ?? selectedBarColor)
                  : (segment.pointColor ?? segment.barColor ?? barColor)
              ..style = PaintingStyle.fill;

            if (isCircle) {
              canvas.drawCircle(Offset(barCenterX, valueY), sizePx / 2, paint);
            } else {
              final rect = Rect.fromCenter(center: Offset(barCenterX, valueY), width: sizePx, height: sizePx);
              final pr = segment.pointRadius ?? const BorderRadius.all(Radius.circular(2));
              canvas.drawRRect(
                RRect.fromRectAndCorners(
                  rect,
                  topLeft: pr.topLeft,
                  topRight: pr.topRight,
                  bottomLeft: pr.bottomLeft,
                  bottomRight: pr.bottomRight,
                ),
                paint,
              );
            }
          }
        }
      }
    }

    // Draw selection
    if (selectedBar != null) {
      print("selectedBar: $selectedBar");
      final xIndex = x.xList.indexOf(selectedBar!.x);
      if (xIndex != -1) {
        final barSpacingRatio = widget.barSpacingRatio ?? (x.xList.length > 20 ? 1.0 : 1.5);
        final availableWidth = (chartEndX - chartStartX);
        final barWidth = availableWidth / (x.xList.length * (1 + barSpacingRatio) + barSpacingRatio);
        final barSpacing = barWidth * barSpacingRatio;
        final xPos = chartStartX + barSpacing + xIndex * (barWidth + barSpacing) + barWidth / 2;

        if (widget.showSelectedVerticalLine) {
          final paint = Paint()
            ..color = selectedLineColor
            ..strokeWidth = selectedLineWidth;
          canvas.drawLine(Offset(xPos, size.height - xAxisHeight), Offset(xPos, 0), paint);
        }

        if (widget.selectedMarkTopBuilder == null) {
          final textPainter = TextPainter(
            text: TextSpan(
              text: '${selectedBar!.segments.fold<double>(0, (prev, e) => prev + e.end - e.start).toInt()}\n${selectedBar!.x}',
              style: TextStyle(
                color: selectedTextColor,
                fontSize: selectedTextSize,
              ),
            ),
            textAlign: TextAlign.center,
            textDirection: TextDirection.ltr,
          );
          textPainter.layout();

          final rRect = RRect.fromRectAndRadius(
            Rect.fromCenter(center: Offset(xPos, -textPainter.height / 2 - 5), width: textPainter.width + 10, height: textPainter.height + 5),
            const Radius.circular(5),
          );
          final bgPaint = Paint()..color = Colors.orange;
          canvas.drawRRect(rRect, bgPaint);

          textPainter.paint(canvas, Offset(xPos - textPainter.width / 2, -textPainter.height - 5));
        }
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}